/*Copyright (c) 2012 Nicolás Zalaquett

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/

package extrae;

import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.Button;
import org.jfxtras.lang.XObject;
import org.jfxtras.scene.control.XTableColumn;
import org.jfxtras.scene.control.renderer.StringAutoRenderer;
import org.jfxtras.scene.control.XTableView;
import javafx.reflect.FXLocal;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.CustomNode;
import javafx.ext.swing.SwingButton;
import extrae.TablaJava.SwingTable;
import extrae.TablaJava.TableRow;
import extrae.TablaJava.TableCell;
import extrae.TablaJava.TableColumn;
import extrae.Grafico.GraficoNode;
import javafx.scene.chart.ScatterChart.Data;
import extrae.TablaJava.modelo;
import java.lang.Exception;
import com.sun.javafx.async.BackgroundTask;
import java.lang.Thread;
import javax.swing.JOptionPane;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.util.Math;

/**
 * @author lojkoro
 */
public class Tabla extends CustomNode {
public var selection: Integer;
public var filas:Fila[]=[Fila{}];
public var headerColumnas:TableColumn[]=[
                    TableColumn {
                        text: "Col0"
                    },
                    TableColumn {
                        text: "Col1"
                    },
                    TableColumn {
                        text: "Col2"
                    },
                    TableColumn {
                        text: "Col3"
                    },
                    TableColumn {
                        text: "Col4"
                    },
                    TableColumn {
                        text: "Col5"
                    },
                    TableColumn {
                        text: "Col6"
                    },
                    TableColumn {
                        text: "Col7"
                    },
                    TableColumn {
                        text: "Col8"
                    },
                    TableColumn {
                        text: "Col9"
                    }];
public var agregarRow:Button=Button{
    layoutX:bind (10)
    layoutY:bind scene.height-25
    text:"Agregar Fila"
    action:addRow
    };
public var borraRow:Button=Button{
    layoutX:bind (agregarRow.width + 15)
    layoutY:bind scene.height-25
    text:"Borrar Fila"
    action:delRow
    };
public var abrir:Button=Button{
    layoutX:bind (borraRow.width + agregarRow.width + 20)
    layoutY:bind scene.height-25
    text:"Abrir"
    disable:true
    action:function():Void{}
    };
public var guardar:Button=Button{
    layoutX:bind (abrir.width + borraRow.width + agregarRow.width + 25)
    layoutY:bind scene.height-25
    text:"Guardar"
    action:function():Void{}
    disable:true
    };
public var graficar:Button=Button{
    layoutX:bind (abrir.width + borraRow.width + agregarRow.width + 42 + guardar.width + xLabel.width + yLabel.width + choiceX.width + choiceY.width)
    layoutY:bind scene.height-25
    text:"Graficar"
    action:aGraficar
    };
public var xLabel:Label=Label{
    text:"x : "
    layoutX:bind (abrir.width + borraRow.width + agregarRow.width + 32 + guardar.width)
    layoutY:bind scene.height-25};
public var yLabel:Label=Label{
    text:"y : "    
    layoutX:bind (abrir.width + borraRow.width + agregarRow.width + 36 + guardar.width + xLabel.width + choiceX.width)
    layoutY:bind scene.height-25};
public var choiceX:ChoiceBox=ChoiceBox{
    items:bind [for(h in headerColumnas) h.text]
    layoutX:bind (abrir.width + borraRow.width + agregarRow.width + 34 + guardar.width + xLabel.width)
    layoutY:bind scene.height-25};
public var choiceY:ChoiceBox=ChoiceBox{
    items:bind [for(h in headerColumnas) h.text]
    layoutX:bind (abrir.width + borraRow.width + agregarRow.width + 38 + guardar.width + xLabel.width + yLabel.width + choiceX.width)
    layoutY:bind scene.height-25};
public var grupoBotones:Group=Group{
    content:[agregarRow,graficar,abrir,guardar,borraRow,xLabel,yLabel,choiceX,choiceY]
};
public function aGraficar():Void{
            var x=choiceX.selectedIndex;
            var y=choiceY.selectedIndex;
            var xT="{choiceX.selectedItem}";
            var yT="{choiceY.selectedItem}";
            if(x>=0 and y>=0){
            graficar.text="Graficando...";
            graficar.disable=true;
            var resultado: Integer = JOptionPane.showConfirmDialog(null, 
                                    "Es esta información correcta: \nColumnas seleccionadas : x: {choiceX.selectedItem} / y: {choiceY.selectedItem}",
                                    "Graficar",
                                    JOptionPane.OK_CANCEL_OPTION);

            if(resultado==JOptionPane.OK_OPTION){
            var graf: Stage;
            var grafico: GraficoNode = GraficoNode {};
            var dat:Data[]=[];
            var m=tabla.tabla.table.getModel() as modelo;
            for (j in [0..tabla.tabla.rows.size()-1]){
                insert Data{xValue:(m.getValueAt(j,x) as Number)
                            yValue:(m.getValueAt(j,y) as Number)} into dat;
            }
            grafico.addDatosTabla(dat,xT,yT);
            graf = Stage {
                        title: "Gráfico"
                        scene: Scene {
                            width: 600
                            height: 400
                            content: [grafico,] }
                    };
                    }
            graficar.text="Graficar";
            graficar.disable=false;}
            else{
                JOptionPane.showMessageDialog(null, "Seleccionar las columnas a graficar.",
                                "No se puede graficar", JOptionPane.INFORMATION_MESSAGE);
                }
}
public function delRow():Void{
    delete filas[selection];
    }
public function addRow():Void{
    insert Fila{} into filas;
    }
public function cambiarTitulo():Void{}
public function addDatos(medicion:MedicionAnaloga):Void{
    var datosActivos:ArregloDatos[]=[];
    var j=0;
    var Ndat=0;
    var maxSize:Integer=0;
    for (i in [0..3]){
        if(medicion.parametros.canalActivo[i]){
            headerColumnas[j].setText(medicion.parametros.canalSensor[i].nombre);
            insert medicion.Datos[i] into datosActivos;
            j++;
            maxSize=Math.max(medicion.Datos[i].Datos.size(),maxSize);
            }
        Ndat=medicion.Datos[i].Datos.size()-1;
        }
    headerColumnas[j].setText("Tiempo {medicion.parametros.unidadesPalabra()}");
    var tiempos:ArregloDatos=ArregloDatos{};
    for (i in [0..Ndat]){
        insert medicion.parametros.valorTasa*i into tiempos.Datos;
    }
    insert tiempos into datosActivos;
    addFilas(datosActivos,maxSize);
    }
public function addDatos(medicion:MedicionDigital,velocidad:Integer):Void{
    if(velocidad==0){
    var datosActivos:ArregloDatos[]=[];
    var j=0;
    var maxSize:Integer=0;
    for (i in [0..3]){
        if(medicion.parametros.canalActivo[i]){
            headerColumnas[j].setText(medicion.parametros.canalSensor[i].nombre);
            insert medicion.Datos[i] into datosActivos;
            j++;
            maxSize=Math.max(medicion.Datos[i].Datos.size(),maxSize);
            }
        }
    addFilas(datosActivos,maxSize);}
    else if(velocidad==1){
    var datosActivos:ArregloDatos[]=[];
    var j=0;
    var maxSize:Integer=0;
    for (i in [0..3]){
        if(medicion.parametros.canalActivo[i]){
            headerColumnas[j].setText("Tiempo [s] Canal {i+1}/{medicion.parametros.canalSensor[i].nombre}");
            headerColumnas[j+1].setText("Velocidad [m/s] Canal {i+1}/{medicion.parametros.canalSensor[i].nombre}");
            insert sacaTiempoyVel(medicion.Datos[i],medicion.parametros.canalSensor[i].tipoInterrupcion,medicion.parametros.canalSensor[i].regleta) into datosActivos;
            j+=2;
            maxSize=Math.max(datosActivos[datosActivos.size()-1].Datos.size(),maxSize);
            }
        }
    addFilas(datosActivos,maxSize);
        }
    else{
       var datosActivos:ArregloDatos[]=[];
    var j=0;
    var maxSize:Integer=0;
    for (i in [0..3]){
        if(medicion.parametros.canalActivo[i]){
            headerColumnas[j].setText("Tiempo [s] Canal {i+1}/{medicion.parametros.canalSensor[i].nombre}");
            headerColumnas[j+1].setText("Posición [m]  Canal {i+1}/{medicion.parametros.canalSensor[i].nombre}");
            insert sacaTiempoyPos(medicion.Datos[i],medicion.parametros.canalSensor[i].tipoInterrupcion,medicion.parametros.canalSensor[i].regleta) into datosActivos;
            j+=2;
            maxSize=Math.max(datosActivos[datosActivos.size()-1].Datos.size(),maxSize);
            }
        }
    addFilas(datosActivos,maxSize);
    }

    }
public function sacaTiempoyVel(tiempos:ArregloDatos,tipo:Boolean,regleta:Integer):ArregloDatos[]{
        var vels:ArregloDatos[]=[ArregloDatos{},ArregloDatos{}];
        var counterVel=0;
        var tAnterior:Double;
        var tInicial:Double;
        for(t in tiempos.Datos){
            if (counterVel==0){
                tInicial=t;
                }
            if (tipo) {
                    if (counterVel > 0) {
                        insert ((regleta)) / ((t - tAnterior) / 1000) into vels[1].Datos;
                        insert (t+tAnterior-tInicial)/2000000 into vels[0].Datos;
                    }
                    tAnterior=t;
                }
                else
                {
                    if (counterVel == 1) {
                        insert ((regleta)) / ((t - tAnterior) / 1000) into vels[1].Datos;
                        insert (t+tAnterior-tInicial)/2000000 into vels[0].Datos;
                        counterVel = -1;
                    }
                    tAnterior=t;

                }
        counterVel++;
        }

        return vels;
    }
public function sacaTiempoyPos(tiempos:ArregloDatos,tipo:Boolean,regleta:Integer):ArregloDatos[]{
        var poss:ArregloDatos[]=[ArregloDatos{},ArregloDatos{}];
        var pos=0.0;
        var tiempo:Double=0.0;
        for(t in tiempos.Datos){
                        pos += (regleta as Double)/1000;
                        tiempo= (t)/2000000;
                        insert pos into poss[1].Datos;
                        insert tiempo into poss[0].Datos;
                }
        return poss;
    }
public function addFilas(datos:ArregloDatos[],maxSize:Integer):Void{
    var N=maxSize;
    var NCol=datos.size();
    filas=[];
    tabla.columnas=[];
    tabla.columnas=headerColumnas;
    for (i in [0..N-1]){
        var f:Fila=Fila{};
        for(j in [0..NCol-1]){
        try{
        f.ponerVal(j, datos[j].Datos[i]);}
        catch(e:Exception){}
        }
        insert f into filas;
    }
}
public var tabla:TablaSola=TablaSola{
                            filas:bind filas with inverse
                            columnas:headerColumnas
                            };
public override function create(): Node {
        Group {
            content: [tabla,grupoBotones]
        }
    }}
public class Fila{
    public var c0: Double=0.0;
    public var c1: Double=0.0;
    public var c2: Double=0.0;
    public var c3: Double=0.0;
    public var c4: Double=0.0;
    public var c5: Double=0.0;
    public var c6: Double=0.0;
    public var c7: Double=0.0;
    public var c8: Double=0.0;
    public var c9: Double=0.0;
    public function ponerVal(i:Integer,val:Double):Void{
        if(i==0){c0=val;}
        if(i==1){c1=val;}
        if(i==2){c2=val;}
        if(i==3){c3=val;}
        if(i==4){c4=val;}
        if(i==5){c5=val;}
        if(i==6){c6=val;}
        if(i==7){c7=val;}
        if(i==8){c8=val;}
        if(i==9){c9=val;}
    }
    public function getVal(i:Integer):Double{
        if(i==0){return c0}
        else if(i==1){return c1;}
        else if(i==2){return c2;}
        else if(i==3){return c3;}
        else if(i==4){return c4;}
        else if(i==5){return c5;}
        else if(i==6){return c6;}
        else if(i==7){return c7;}
        else if(i==8){return c8;}
        else if(i==9){return c9;}
        else{return -1;}
    }
}
public class TablaSola extends CustomNode{
    public var filas:Fila[];
    public var columnas:TableColumn[];
    public var tabla:SwingTable=SwingTable{
                width: bind scene.width
                height: bind (scene.height-30)
                columns: bind columnas
                rows: bind [for(p in filas) {
                    TableRow{
                        cells: [
                            TableCell {
                                text:bind p.c0
                            },TableCell {
                                text:bind p.c1
                            },TableCell {
                                text:bind p.c2
                            },TableCell {
                                text:bind p.c3
                            },TableCell {
                                text:bind p.c4
                            },TableCell {
                                text:bind p.c5
                            },TableCell {
                                text:bind p.c6
                            },TableCell {
                                text:bind p.c7
                            },TableCell {
                                text:bind p.c8
                            },TableCell {
                                text:bind p.c9
                            },

                        ]
                    }}
                    ]
                selection: bind selection with inverse
            };
  public override function create(): Node {
        Group {
            content: [tabla]
        }
    }
}
